#include <stdio.h>
#include <stdlib.h>
#include "matrix.h"
#include "rational.h"

void getIntMatrix(int*** intMatrix, int rows, int cols) {

    int i, j;
    
    int** tmpMatrix;

    /* allocate space for adjacency matrix */
    tmpMatrix = (int**) malloc(cols * sizeof (int *));
    for (i = 0; i < cols; i++) {
        tmpMatrix[i] = (int*) malloc(rows * sizeof (int));
    }
    
    *intMatrix = tmpMatrix;
    
}

void copyIntMatrix(int*** sourceIntMatrix, int*** modifiedIntMatrix, int sourceStartRow, int sourceStartColumn, int modifiedStartRow, int modifiedStartColumn, int rowsToCopy, int colsToCopy) {
    
    int i,j;
    
    for (j = 0; j < colsToCopy; j++) {
        for (i = 0; i < rowsToCopy; i++) {
            (*modifiedIntMatrix)[modifiedStartColumn+j][modifiedStartRow+i] = (*sourceIntMatrix)[sourceStartColumn+j][sourceStartRow+i];
        }
    }
    
}

void getIntVector(int** intVector, int size) {
    
    int* tmpVector;
    
    /* allocate space for matrix */
    tmpVector = (int*)calloc(size, sizeof (int)); /* initialize with 0 */
    
    *intVector = tmpVector;
    
}

void copyIntVector(int** sourceIntVector, int** modifiedIntVector, int size) {
    
    int i;
    for (i = 0; i < size; i++) {
        (*modifiedIntVector)[i] = (*sourceIntVector)[i];
    }
    
}

void resizeIntVector(int** intVector, int oldSize, int newSize) {
    
    int i,minSize;
    
    /* create new vector */
    int* newIntVector;
    getIntVector(&newIntVector, newSize); /* initialized with zeros */
    
    if ( oldSize < newSize ) {
        minSize = oldSize;
    } else {
        minSize = newSize;
    }
    
    copyIntVector(intVector, &newIntVector, minSize);
    
    /* deallocate previous vector */
    /* free(*intVector); */
    
    *intVector = newIntVector;

}

void printIntMatrix(int ***intMatrix,int rows, int cols) {

    int i, j;

    printf("\nMatrix:\n");

    /* Print Matrix */
    for (i = 0; i < rows; i++) {
        for (j = 0; j < cols; j++) {
            printf("%5d ", (*intMatrix)[j][i]);
        }
        printf("\n");
    }
    printf("\n");
    
}

void printIntVector(int **intVector, int size) {
    
    int j;
    
    printf("\nVector:\n");
    
    /* Print Vector */
    for (j = 0; j < size; j++) {
        printf("%5d ", (*intVector)[j]);
    }
    printf("\n");
    
}

void getRationalMatrix(rational*** rationalMatrix, int rows, int cols) {
    
    rational** tmpMatrix;
    int i;
    
    /* allocate space for matrix */
    tmpMatrix = (rational**) malloc(cols * sizeof (rational*));
    for (i = 0; i < cols; i++) {
        tmpMatrix[i] = (rational*) calloc(rows, sizeof (rational)); /* initialize with 0 */
    }
    
    *rationalMatrix = tmpMatrix;
    
}

void convertIntToRationalMatrix(int*** intMatrix, rational*** rationalMatrix, int rows, int cols) {
    
    int i,j;
    
    for (i = 0; i < rows; i++) {
        for (j = 0; j < cols; j++) {
            (*rationalMatrix)[j][i].numerator = (*intMatrix)[j][i];
            (*rationalMatrix)[j][i].denominator = 1;
        }
    }
    
}

void convertIntToRationalVector(int** intVector, rational** rationalVector, int size) {
    
    int i;
    
    for (i = 0; i < size; i++) {
        (*rationalVector)[i].numerator = (*intVector)[i];
        (*rationalVector)[i].denominator = 1;
    }
    
}

void printRationalMatrix(rational*** rationalMatrix, int rows, int cols) {
    
    int i, j;

    printf("\nMatrix:\n");

    /* Print Matrix */
    for (i = 0; i < rows; i++) {
        for (j = 0; j < cols; j++) {
            printRational((*rationalMatrix)[j][i]);
            printf(" ");
        }
        printf("\n");
    }
    printf("\n");
    
}

void getRationalVector(rational** rationalVector, int size) {
    
    rational* tmpVector;
    int i;
    
    /* allocate space for matrix */
    tmpVector = (rational*) calloc(size, sizeof (rational)); /* initialize with 0 */
    
    /* set denominators to 1 to avoid 0/0 error */
    for (i = 0; i < size; i++) {
        tmpVector[i].denominator = 1;
    }
    
    *rationalVector = tmpVector;
    
}

void copyRationalVector(rational** sourceRationalVector, rational** modifiedRationalVector, int size) {
    
    int i;
    for (i = 0; i < size; i++) {
        (*modifiedRationalVector)[i].numerator = (*sourceRationalVector)[i].numerator;
        (*modifiedRationalVector)[i].denominator = (*sourceRationalVector)[i].denominator;
    }
    
}

void copyRationalMatrix(rational*** sourceRationalMatrix, rational*** modifiedRationalMatrix, int sourceStartRow, int sourceStartColumn, int modifiedStartRow, int modifiedStartColumn, int rowsToCopy, int colsToCopy) {
    
    int i,j;
    
    for (j = 0; j < colsToCopy; j++) {
        for (i = 0; i < rowsToCopy; i++) {
            (*modifiedRationalMatrix)[modifiedStartColumn+j][modifiedStartRow+i].numerator = (*sourceRationalMatrix)[sourceStartColumn+j][sourceStartRow+i].numerator;
            (*modifiedRationalMatrix)[modifiedStartColumn+j][modifiedStartRow+i].denominator = (*sourceRationalMatrix)[sourceStartColumn+j][sourceStartRow+i].denominator;
        }
    }
    
}

void resizeRationalVector(rational** rationalVector, int oldSize, int newSize) {
    
    int i,minSize;
    
    /* create new vector */
    rational* newRationalVector;
    getRationalVector(&newRationalVector, newSize); /* initialized with zeros */
    
    if ( oldSize < newSize ) {
        minSize = oldSize;
    } else {
        minSize = newSize;
    }
    
    copyRationalVector(rationalVector, &newRationalVector, minSize);
    
    /* deallocate previous vector */
    /* free(*intVector); */
    
    *rationalVector = newRationalVector;

}

void getRationalScalarRationalVectorPdt(rational rationalScalar, rational** rationalVector, int size, rational** pdtRationalVector) {
    
    int i;
    
    for (i = 0; i < size; i++) {
        (*pdtRationalVector)[i] = rMul((*rationalVector)[i], rationalScalar);
    }
    
}

void printRationalVector(rational** rationalVector, int size) {
    
    int j;
    
    printf("\nVector:\n");
    
    /* Print Vector */
    for (j = 0; j < size; j++) {
        printRational((*rationalVector)[j]);
        printf(" ");
    }
    printf("\n");
    
}

